﻿/*                       NOTICE
 * 
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-10-C-0001, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * Approved for Public Release: 11-2435
 * © 2011 The MITRE Corporation. All Rights Reserved. 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Surface;
using Microsoft.Surface.Core;
using TUIO;

namespace GRIP
{
    public class Surface
    {
        private SurfaceWindow surface;

        private int left;
        private int top;
        private float width;
        private float height;
        private List<TuioContact> contacts = new List<TuioContact>();
        private string source;

        private List<Action<TuioContact>> contactAddedListeners = new List<Action<TuioContact>>();
        private List<Action<TuioContact>> contactChangedListeners = new List<Action<TuioContact>>();
        private List<Action<TuioContact>> contactRemovedListeners = new List<Action<TuioContact>>();

        public List<TuioContact> getContacts()
        {
            return new List<TuioContact>(contacts);
        }

        public void registerContactAddedListener(Action<TuioContact> listener)
        {
            contactAddedListeners.Add(listener);
        }
        public void registerContactChangedListener(Action<TuioContact> listener)
        {
            contactChangedListeners.Add(listener);
        }
        public void registerContactRemovedListener(Action<TuioContact> listener)
        {
            contactRemovedListeners.Add(listener);
        }

        public Surface(string source)
        {
            Thread t = new Thread(() =>
            {
                using (SurfaceWindow newSurface = new SurfaceWindow(this))
                {
                    surface = newSurface;
                    surface.Run();
                }
            });
            t.Start();
            while (surface == null) ;

            //surface.registerContactAddedListener(contactTarget_ContactAdded);
            //surface.registerContactChangedListener(contactTarget_ContactChanged);
            //surface.registerContactRemovedListener(contactTarget_ContactRemoved);
        }

        public void setDimensions(int top, int left, float width, float height)
        {
            this.top = top;
            this.left = left;
            this.width = width;
            this.height = height;
        }

        public void contactAdded(object sender, ContactEventArgs e)
        {
            TuioContact newContact = new TuioContact(
                source,
                e.Contact.Id,
                TuioContact.ContactType.GenericContact,
                (e.Contact.CenterX - left) / width,
                (e.Contact.CenterY - top) / height,
                0);
            contacts.Add(newContact);
            foreach (Action<TuioContact> listener in contactAddedListeners)
                listener(newContact);
        }

        public void contactChanged(object sender, ContactEventArgs e)
        {
            for (int i = 0; i < contacts.Count; i++)
            {
                TuioContact contact = contacts[i];
                if (e.Contact.Id == contact.session_id)
                {
                    contact.xpos = (e.Contact.CenterX - left) / width;
                    contact.ypos = (e.Contact.CenterY - top) / height;
                    foreach (Action<TuioContact> listener in contactChangedListeners)
                        listener(contact);
                    return;
                }
            }
        }

        public void contactRemoved(object sender, ContactEventArgs e)
        {
            for (int i = 0; i < contacts.Count; i++)
            {
                TuioContact contact = contacts[i];
                if (e.Contact.Id == contact.session_id)
                {
                    contacts.RemoveAt(i);
                    foreach (Action<TuioContact> listener in contactAddedListeners)
                        listener(contact);
                    return;
                }
            }
        }
    }
}
